package com.allen.study.domain.utils.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @ClassName: SecurityConfig
 * @Author: AllenSun
 * @Date: 2025/3/6 22:16
 */
@Configuration
//开启webSecurity服务
@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    private MyUserDetailsService myUserDetailsService;

    // 验证 JWT 并进行身份验证。
    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        // Admin Server 需要访问静态资源
        return (web) -> web.ignoring().antMatchers("http://localhost:8091/**");
    }

    /*
     * 配置权限相关的配置
     * 安全框架本质上是一堆的过滤器，称之为过滤器链，每一个过滤器链的功能都不同
     * 设置一些链接不要拦截
     * */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .csrf().disable() // 关闭csrf
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)  // 插入JWT过滤器
                .authorizeRequests(auth -> auth
                        // 放行 Swagger 相关路径
                        .antMatchers(
                                "/auth/login",//路径允许所有用户访问，用于用户登录获取 JWT。
                                "/employeelogin/**",
                                "/v2/api-docs/**",
                                "/v3/api-docs/**",
                                "/swagger-resources/configuration/ui",
                                "/swagger-resources/**",
                                "/swagger-resources/configuration/security",
                                "/swagger-ui/**",
                                "/webjars/**",
                                "/actuator/**",
                                "/instances/**",
                                "/assets/**",
                                "/applications/**",
                                "/**"
                                ).permitAll()
                        // .antMatchers("/login").hasRole("ADMIN")
                        .anyRequest()
                        .authenticated()
                )
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) //不使用会话管理，因为 JWT 是无状态的。
        ;
        //关闭csrf
        // httpSecurity.csrf(it->it.disable());
        // httpSecurity.authorizeHttpRequests(it->
        //         it.requestMatchers("/4.2.0/employeelogin/login").permitAll()  //设置登录路径所有人都可以访问
        //                 .anyRequest().authenticated()  //其他路径都要进行拦截
        // );
        //表单
        // httpSecurity.formLogin(from->
        //         from.loginPage("/login")   //跳转到自定义的登录页面
                        // .loginProcessingUrl("/login")  //处理前端的请求，与from表单的action一致即可
                        // .defaultSuccessUrl("/index")  //默认的请求成功之后的跳转页面，直接访问登录页面
        // );
        return httpSecurity.build();
    }



    @Bean
    public AuthenticationManager authenticationManager(PasswordEncoder passwordEncoder){
        DaoAuthenticationProvider provider=new DaoAuthenticationProvider();
        //将编写的UserDetailsService注入进来
        provider.setUserDetailsService(myUserDetailsService);
        //将使用的密码编译器加入进来
        provider.setPasswordEncoder(passwordEncoder);
        //将provider放置到AuthenticationManager 中
        ProviderManager providerManager=new ProviderManager(provider);
        return providerManager;
    }

    /*
     * 在security安全框架中，提供了若干密码解析器实现类型。
     * 其中BCryptPasswordEncoder 叫强散列加密。可以保证相同的明文，多次加密后，
     * 密码有相同的散列数据，而不是相同的结果。
     * 匹配时，是基于相同的散列数据做的匹配。
     * Spring Security 推荐使用 BCryptPasswordEncoder 作为密码加密和解析器。
     * */
    @Bean
    public PasswordEncoder passwordEncoder(){
        // return new CustomBCryptPasswordEncoder();
        return new BCryptPasswordEncoder();
        // return NoOpPasswordEncoder.getInstance(); // 明文处理，不做加密
    }

    // @Bean
    // public AuthenticationSuccessHandler customAuthenticationSuccessHandler() {
    //     return new CustomAuthenticationSuccessHandler();
    // }
    //
    // @Bean
    // public AuthenticationFailureHandler customAuthenticationFailureHandler() {
    //     return new CustomAuthenticationFailureHandler();
    // }
}

